#ifndef _NET_H_INCLUDED_
#define _NET_H_INCLUDED_

#include "defines.h"

typedef struct {
    uint8 src_MAC[6];
    uint8 dst_MAC[6];
    uint8 src_IP[4];
    uint8 dst_IP[4];
    uint16 src_port;
    uint16 dst_port;
} net_params;

typedef struct {
    uint8 eth_dst_MAC[6];
    uint8 eth_src_MAC[6];
    uint16 eth_ethernet_type; /* IP: 0x0800, ARP: 0x0806 */
} ethernet_header;

typedef struct {
    uint16 arp_hardware_type; /* Ethernet: 1 */
    uint16 arp_protocol_type; /* IPv4: 0x0800 */
    uint8 arp_hardware_length; // 6
    uint8 arp_protocol_length; // 4
    uint16 arp_operation; // request: 1, reply: 2
    uint8 arp_src_MAC[6];
    uint8 arp_src_IP[4];
    uint8 arp_dst_MAC[6];
    uint8 arp_dst_IP[4];
} arp_packet;

typedef struct {
    uint8 ip_version_length;
    uint8 ip_service_type;
    uint16 ip_total_length;
    uint16 ip_id;
    uint16 ip_flags_fragment_offset;
    uint8 ip_time_to_live;
    uint8 ip_protocol; // ICMP: 1, TCP: 6, UDP: 17
    uint16 ip_checksum;
    uint8 ip_src_IP[4];
    uint8 ip_dst_IP[4];
} ip_header;

typedef struct {
    uint16 udp_src_port;
    uint16 udp_dst_port;
    uint16 udp_length;
    uint16 udp_checksum;
} udp_header;

int arp_request(uint8 *buffer, net_params *np);
int arp_reply(uint8 *buffer, net_params *np);
int mac_get(uint8 *buffer, net_params *np);

int send_by_udp(uint8 *buffer, uint16 size, net_params *np);

int tftp_down(uint8 *buffer, net_params *pa, const char *filename, 
              uint8 *downbuf, uint32 downsize, uint32 *sizep);

int parse_IP(uint8 *buf, const char *str);
uint16 ip_checksum(uint8 *data, uint16 size);
uint16 udp_checksum(uint8 *data, uint16 size, uint8 *src_IP, uint8 *dst_IP);

#endif
